package com.ihr360.expr.function.excel;


import com.ihr360.expr.ExprArray;
import com.ihr360.expr.ExprError;
import com.ihr360.expr.ExprException;
import com.ihr360.expr.context.IEvaluationContext;
import com.ihr360.expr.core.AbstractFunction;
import com.ihr360.expr.core.Expr;
import com.ihr360.expr.core.ExprFunction;
import com.ihr360.expr.core.ExprType;
import com.ihr360.expr.core.ExprVariable;
import com.ihr360.expr.utils.ExprUtils;

/**
 * VLOOKUP(search_criteria,array,index,sorted)
 */
public class VLOOKUP extends AbstractFunction {
    @Override
    public Expr evaluate(IEvaluationContext context, Expr[] args)
            throws ExprException {
        assertMinArgCount(args, 3);
        assertMaxArgCount(args, 4);
        return arrayLookup(context, args);

    }


    public Expr arrayLookup(IEvaluationContext context, Expr[] args) throws ExprException {
        Expr ev = ExprUtils.evalArg(context, args[0]);
        int index = asInteger(context, args[2], true);

        Expr array = args[1];
        if (array instanceof ExprVariable) {
            array = ExprUtils.evalArg(context, array);
        }
        if (array.type == ExprType.Missing) {
            return new ExprError("#VALUE", "无法获取数组", args[1].toString());
        }
        if (array instanceof ExprArray) {
            ExprArray exprArray = (ExprArray) array;
            if (index > exprArray.columns()) {
                return ExprError.INDEX_RANGE;
            }
            int rowSize = exprArray.rows();
            int row;
            int hitRow = -1;
            int lastCompare = Integer.MIN_VALUE;
            for (row = 0; row < rowSize; row++) {
                Expr expr = exprArray.get(row, 0);
                if (expr instanceof ExprFunction){
                    expr = ExprUtils.evalArg(context, expr);
                }
                int compare = ExprUtils.compareToNotStrict(context, ev, expr);
                if (compare == 0) {
                    hitRow = row;
                    break;
                }
                //if (lastCompare > 0 && lastCompare != Integer.MIN_VALUE && compare < 0) {
                if (lastCompare != Integer.MIN_VALUE && compare < 0) {
                    hitRow = row - 1;
                    break;
                }
                if (compare > 0 && row == rowSize - 1) {
                    row = row - 1;
                    break;
                }
                lastCompare = compare;
            }
            if (rowSize == 1) {
                hitRow = 0;
            }
            if (hitRow >= 0) {
                Expr expr= exprArray.get(hitRow, index - 1);
                if (expr instanceof ExprFunction){
                    expr = ExprUtils.evalArg(context, expr);
                }
                return expr;
            }
        }
        return ExprError.VALUE;
    }
}
